<?php

/**
 * htconsole htpasswd tool
 *
 * @package    htconsole
 * @author     Tiefeng Jia <jiatiefeng@gmail.com>
 * @copyright  MIT License
 * @version    v1.0
 */


define('INSTALLED_DIRECTORY', basename(dirname(__FILE__)));
define('HTPASSWD_DIRECTORY_ROOT', dirname(dirname(__FILE__)));
define('HTPASSWD_FILE', '.htpasswd');
define('HTACCESS_FILE', '.htaccess');
define('DS', DIRECTORY_SEPARATOR);
define('EXAMPLE_HTACCESS', <<<EOL

# Added by "htconsole": {date}
AuthUserFile "{file}"
AuthType Basic
AuthName "Project Preview"
Require valid-user

EOL
);

require_once('includes/htpasswd.php');

function getDirectoryList($dir) {
    $result = array();

    $d = dir($dir);
    while (false !== ($entry = $d->read())) {
        if (!in_array($entry, array('.', '..')) && is_dir($dir . DS . $entry)) {
            $htpasswd = '';
            if (file_exists($dir . DS . $entry . DS . HTACCESS_FILE)) {
                $file_content = file_get_contents($dir . DS . $entry . DS . HTACCESS_FILE);
                //var_dump($file_content);
                if (preg_match('/\s*AuthUserFile\s["]?([^"]*)["]?/i', $file_content, $match)) {
                    $htpasswd = $match[1];
                }
            }
            $result[$entry] = $htpasswd;
        }
    }
    $d->close();
    ksort($result);

    return $result;
}

$message = '';

if (isset($_REQUEST['g'])) {
    
    switch ($_REQUEST['g']) {

        case 'add_protection':
            $d = $_REQUEST['d'];
            $d = str_replace(array('..\\', '../'), array('', ''), $d);
            if (!empty($d)) {

                $htaccess = HTPASSWD_DIRECTORY_ROOT . DS . $d . DS . HTACCESS_FILE;
                $htpasswd = HTPASSWD_DIRECTORY_ROOT . DS . $d . DS . HTPASSWD_FILE;
                $check = false;
                if (file_exists($htaccess)) {
                    $file_content = file_get_contents($htaccess);
                    if (preg_match('/\s*AuthUserFile\s["]?(.*)["]?/i', $file_content, $match)) {
                        $check = true;
                    }
                }
                if (!$check) {
                    if (false === file_put_contents($htaccess, str_replace(array('{file}', '{date}'), array($htpasswd, date('m/d/Y H:i:s')), EXAMPLE_HTACCESS), FILE_APPEND)) {
                        $message = 'Failed to write &quot;' . $htaccess . '&quot;';
                    } else {
                        $message = '&quot;' . $htaccess . '&quot; is updated. Directory now be protected.';
                    }
                } else {
                    $message = 'Directy &quot;' . $d . '&quot; is already protected.';
                }
            } else {
                $message = 'Invalid usage.';
            }
            break;

        case 'add':
            $d = $_REQUEST['d'];
            $d = str_replace(array('..\\', '../'), array('', ''), $d);
            if (!empty($d)) {
                $user = trim($_REQUEST['user']);
                $passwd = trim($_REQUEST['passwd']);

                if ($user != '' && $passwd != '') {
                    $htpasswd = HTPASSWD_DIRECTORY_ROOT . DS . $d . DS . HTPASSWD_FILE;
                    $pwmanager = new htpasswd($htpasswd);
                    if ($pwmanager->create($user, $passwd) && $pwmanager->save()) {
                        $message = 'User &quot;' . $user . '&quot; added to &quot;' . $d . '&quot;.';
                    } else {
                        $message = 'Failed to create user &quot;' . $user . '&quot; of &quot;' . $d . '&quot;.';
                    }
                    unset($pwmanager);
                } else {
                    $message = 'Username or password is empty.';
                }
            } else {
                $message = 'Invalid usage.';
            }
            break;

        case 'edit':
            $d = $_REQUEST['d'];
            $d = str_replace(array('..\\', '../'), array('', ''), $d);
            if (!empty($d)) {
                $user = trim($_REQUEST['user']);
                $passwd = trim($_REQUEST['passwd']);

                if ($user != '' && $passwd != '') {
                    $htpasswd = HTPASSWD_DIRECTORY_ROOT . DS . $d . DS . HTPASSWD_FILE;
                    $pwmanager = new htpasswd($htpasswd);
                    if ($pwmanager->remove($user) && $pwmanager->create($user, $passwd) && $pwmanager->save()) {
                        $message = 'User &quot;' . $user . '&quot; of &quot;' . $d . '&quot; is updated.';
                    } else {
                        $message = 'Failed to edit user &quot;' . $user . '&quot; of &quot;' . $d . '&quot;.';
                    }
                    unset($pwmanager);
                } else {
                    $message = 'Username or password is empty.';
                }
            } else {
                $message = 'Invalid usage.';
            }
            break;

        case 'remove':
            $d = $_REQUEST['d'];
            $d = str_replace(array('..\\', '../'), array('', ''), $d);
            if (!empty($d)) {
                $user = trim($_REQUEST['user']);

                if ($user != '') {
                    $htpasswd = HTPASSWD_DIRECTORY_ROOT . DS . $d . DS . HTPASSWD_FILE;
                    $pwmanager = new htpasswd($htpasswd);
                    if ($pwmanager->remove($user) && $pwmanager->save()) {
                        $message = 'User &quot;' . $user . '&quot; of &quot;' . $d . '&quot; is removed.';
                    } else {
                        $message = 'Failed to remove user &quot;' . $user . '&quot; of &quot;' . $d . '&quot;.';
                    }
                    unset($pwmanager);
                } else {
                    $message = 'Username is empty.';
                }
            } else {
                $message = 'Invalid usage.';
            }
            break;

    }

}
?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
        <title>HTPASSWD Console</title>
        <link rel="stylesheet" type="text/css" media="screen" href="http://ajax.googleapis.com/ajax/libs/jqueryui/1.8.2/themes/smoothness/jquery-ui.css" />
        <link rel="stylesheet" type="text/css" media="screen" href="includes/main.css" />
        <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js"></script>
        <script type="text/javascript" src="http://ajax.googleapis.com//ajax/libs/jqueryui/1.8.2/jquery-ui.min.js"></script>
        <script type="text/javascript">
            $(function() {
                $("#directories").accordion({ autoHeight: false, animated: false });

                $(".edit_user").click(function() {
                    var f = $("#form_user"), a = $(this), rel = a.attr('rel').split('|');
                    var d = rel[0], u = rel[1];
                    $("div#add").show();
                    f.find('input[name=g]').val('edit');
                    f.find('input[name=d]').val(d);
                    f.find('input[name=user]').val(u).focus();
                    f.find('input[name=passwd]').val('');
                    $("span#form_action").html('Edit');
                });
                $(".add_user").click(function() {
                    var f = $("#form_user"), a = $(this), d = a.attr('rel');
                    $("div#add").show();
                    f.find('input[name=g]').val('add');
                    f.find('input[name=d]').val(d);
                    f.find('input[name=user]').val('').focus();
                    f.find('input[name=passwd]').val('');
                    $("span#form_action").html('Add');
                });
            });
        </script>
    </head>
    <body>
        <div class="header"><a href="index.php">HTPASSWD Console</a></div>
        <?php if (!empty($message)) : ?><div id="message"><?php echo $message; ?></div><?php endif; ?>
        <div class="content">
            <div class="left">
                <div id="add" style="display: none;">
                    <form id="form_user" action="index.php" method="get">
                        <input type="hidden" name="g" value="add" />
                        <input type="hidden" name="d" value="" />
                        <span id="form_action">Add</span>
                        User: <input type="text" name="user" />
                        Password: <input type="text" name="passwd" />
                        <input type="submit" value="Confirm" />
                    </form>
                </div>
                <div id="directories">
<?php
$ds = getDirectoryList(HTPASSWD_DIRECTORY_ROOT);
foreach($ds as $d => $htpasswd) {
    echo '<h3><a href="#">' . $d . '</a></h3>';
    echo '<div>';
    //var_dump($htpasswd);
    if (!empty($htpasswd)) {
        $pwmanager = new htpasswd($htpasswd);
        $users = $pwmanager->users();
        if (empty($users)) {
            echo '<span class="protect-yes">Protected, but no user found.</span> <a href="javascript:;" class="add_user" rel="' . $d . '">Add User</a>';
        } else {
            echo 'Users <a href="javascript:;" class="add_user" rel="' . $d . '">Add</a><br><ul>';
            foreach ($users as $user) {
                echo '<li><a href="javascript:;" class="edit_user" rel="' . $d . '|' . $user . '">' . $user . '</a> <a href="index.php?g=remove&d=' . urlencode($d) . '&user=' . urlencode($user) . '" onclick="return confirm(\'Please confirm to remove [' . $user . '].\');">Remove</a></li>';
            }
            echo '</ul>';
        }
        unset($pwmanager);
    } else {
        echo '<span class="protect-no">Not password protected.</span> <a href="index.php?g=add_protection&d=' . urlencode($d) . '">Add Protection</a> <a href="javascript:;" class="add_user" rel="' . $d . '">Add User</a>';
    }
    echo '</div>';
}
?>
                </div>
            </div>
            <div class="right">
                Example .htaccess File:<br />
                <pre><code><?php echo str_replace('{file}', HTPASSWD_DIRECTORY_ROOT . DS . '[client]' . DS . HTPASSWD_FILE , EXAMPLE_HTACCESS); ?></code></pre>
            </div>
        </div>
        <div class="footer">&copy; 2010 Tiefeng Jia</div>
    </body>
</html>
